#!/usr/bin/env node

const { PrismaClient } = require('@prisma/client');
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');

// 颜色输出
const colors = {
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m',
  reset: '\x1b[0m',
  bold: '\x1b[1m'
};

function log(message, color = 'reset') {
  console.log(`${colors[color]}${message}${colors.reset}`);
}

function logStep(step, message) {
  log(`\n${step} ${message}`, 'bold');
}

function logSuccess(message) {
  log(`✅ ${message}`, 'green');
}

function logWarning(message) {
  log(`⚠️  ${message}`, 'yellow');
}

function logError(message) {
  log(`❌ ${message}`, 'red');
}

function logInfo(message) {
  log(`💡 ${message}`, 'cyan');
}

// 检查数据库连接
async function checkDatabaseConnection() {
  const prisma = new PrismaClient();
  try {
    await prisma.$connect();
    await prisma.$queryRaw`SELECT 1`;
    logSuccess('数据库连接正常');
    return { connected: true, prisma };
  } catch (error) {
    logError(`数据库连接失败: ${error.message}`);
    return { connected: false, error, prisma: null };
  }
}

// 检查表是否存在
async function checkTablesExist(prisma) {
  try {
    const chains = await prisma.chainMonitorConfig.count();
    const tokens = await prisma.monitoredToken.count();
    
    return {
      chainConfigs: { exists: true, count: chains },
      tokens: { exists: true, count: tokens }
    };
  } catch (error) {
    logWarning('数据库表不存在或未迁移');
    return {
      chainConfigs: { exists: false, count: 0 },
      tokens: { exists: false, count: 0 }
    };
  }
}

// 运行命令并输出结果
function runCommand(command, description) {
  try {
    logInfo(`执行: ${command}`);
    const output = execSync(command, { 
      stdio: 'inherit', 
      cwd: process.cwd(),
      encoding: 'utf8' 
    });
    logSuccess(`${description} 完成`);
    return { success: true, output };
  } catch (error) {
    logError(`${description} 失败: ${error.message}`);
    return { success: false, error };
  }
}

// 检查环境变量
function checkEnvironment() {
  const requiredVars = ['DATABASE_URL'];
  const missing = [];
  
  requiredVars.forEach(varName => {
    if (!process.env[varName]) {
      missing.push(varName);
    }
  });
  
  if (missing.length > 0) {
    logError(`缺少必需的环境变量: ${missing.join(', ')}`);
    logInfo('请检查 .env 文件是否存在并包含所有必需的变量');
    return false;
  }
  
  logSuccess('环境变量检查通过');
  return true;
}

// 检查 .env 文件
function checkEnvFile() {
  const envPath = path.join(process.cwd(), '.env');
  const envExamplePath = path.join(process.cwd(), '.env.example');
  
  if (!fs.existsSync(envPath)) {
    logWarning('.env 文件不存在');
    
    if (fs.existsSync(envExamplePath)) {
      logInfo('发现 .env.example 文件，建议复制并配置:');
      logInfo('cp .env.example .env');
    } else {
      logInfo('请创建 .env 文件并配置数据库连接');
    }
    return false;
  }
  
  logSuccess('.env 文件存在');
  return true;
}

// 快速检查是否需要完整设置
async function performQuickCheck() {
  try {
    // 检查环境文件
    const envPath = path.join(process.cwd(), '.env');
    if (!fs.existsSync(envPath)) {
      return { allGood: false, reason: 'missing .env file' };
    }
    
    // 检查数据库连接和数据
    const prisma = new PrismaClient();
    await prisma.$connect();
    
    const chainConfigCount = await prisma.chainMonitorConfig.count();
    const tokenCount = await prisma.monitoredToken.count();
    
    await prisma.$disconnect();
    
    // 如果有基础配置数据，认为环境已就绪
    if (chainConfigCount >= 2 && tokenCount >= 5) {
      return {
        allGood: true,
        stats: {
          chainConfigs: chainConfigCount,
          tokens: tokenCount
        }
      };
    }
    
    return { 
      allGood: false, 
      reason: `insufficient data (chains: ${chainConfigCount}, tokens: ${tokenCount})` 
    };
    
  } catch (error) {
    return { 
      allGood: false, 
      reason: `database connection failed: ${error.message}` 
    };
  }
}

// 主要的设置流程
async function setupDevelopmentEnvironment() {
  log('\n🚀 开发环境智能检测开始...', 'bold');
  
  // 快速检查：如果基础数据都存在，跳过详细设置
  const quickCheck = await performQuickCheck();
  if (quickCheck.allGood) {
    log('\n✅ 开发环境已就绪！', 'green');
    logInfo('检测到完整的配置和数据，无需重新设置');
    logInfo('基础数据统计:');
    logInfo(`  - 链配置: ${quickCheck.stats.chainConfigs} 条`);
    logInfo(`  - 监控代币: ${quickCheck.stats.tokens} 条`);
    log('\n💡 你可以直接使用:', 'cyan');
    logInfo('  npm run dev                    # 启动开发服务器');
    logInfo('  npm run monitor:start          # 启动区块链监控');
    return;
  }
  
  log('\n🔧 检测到需要设置的项目，开始完整设置流程...', 'yellow');
  
  // 步骤 1: 检查环境文件
  logStep('1️⃣', '检查环境配置');
  const envExists = checkEnvFile();
  if (!envExists) {
    logError('请先配置 .env 文件后重新运行');
    process.exit(1);
  }
  
  const envValid = checkEnvironment();
  if (!envValid) {
    process.exit(1);
  }
  
  // 步骤 2: 检查数据库连接
  logStep('2️⃣', '检查数据库连接');
  const dbResult = await checkDatabaseConnection();
  
  if (!dbResult.connected) {
    logError('请检查数据库连接配置');
    process.exit(1);
  }
  
  // 步骤 3: 检查数据库表
  logStep('3️⃣', '检查数据库表结构');
  const tables = await checkTablesExist(dbResult.prisma);
  
  let needsMigration = false;
  if (!tables.chainConfigs.exists || !tables.tokens.exists) {
    needsMigration = true;
  }
  
  // 步骤 4: 运行必要的迁移
  if (needsMigration) {
    logStep('4️⃣', '运行数据库迁移');
    const migrateResult = runCommand('npx prisma migrate dev', '数据库迁移');
    
    if (!migrateResult.success) {
      logError('数据库迁移失败，请手动检查');
      process.exit(1);
    }
    
    // 重新检查表
    const tablesAfterMigration = await checkTablesExist(dbResult.prisma);
    Object.assign(tables, tablesAfterMigration);
  } else {
    logSuccess('数据库表结构正常');
  }
  
  // 步骤 5: 检查和初始化数据
  logStep('5️⃣', '检查基础数据');
  
  let needsSeeding = false;
  
  if (tables.chainConfigs.count === 0) {
    logWarning('链配置数据为空');
    needsSeeding = true;
  } else {
    logSuccess(`链配置: ${tables.chainConfigs.count} 条记录`);
  }
  
  if (tables.tokens.count === 0) {
    logWarning('监控代币数据为空');
    needsSeeding = true;
  } else {
    logSuccess(`监控代币: ${tables.tokens.count} 条记录`);
  }
  
  // 步骤 6: 运行种子数据
  if (needsSeeding) {
    logStep('6️⃣', '初始化基础数据');
    
    const seedResult = runCommand('npx prisma db seed', '基础数据初始化');
    
    if (!seedResult.success) {
      logError('基础数据初始化失败');
      process.exit(1);
    }
    
    // 重新检查数据
    const finalTables = await checkTablesExist(dbResult.prisma);
    logSuccess(`最终数据统计:`);
    logSuccess(`  - 链配置: ${finalTables.chainConfigs.count} 条`);
    logSuccess(`  - 监控代币: ${finalTables.tokens.count} 条`);
  } else {
    logSuccess('基础数据已存在');
  }
  
  // 关闭数据库连接
  await dbResult.prisma.$disconnect();
  
  // 完成消息
  log('\n🎉 开发环境设置完成！', 'green');
  logInfo('现在可以启动监控服务了:');
  logInfo('  npm run dev                    # 启动开发服务器');
  logInfo('  npm run monitor:start          # 启动区块链监控');
  logInfo('  npm run monitor:status         # 查看监控状态');
  
  if (tables.tokens.count <= 10) {
    log('\n💡 提示: 当前只有基础代币数据', 'yellow');
    logInfo('如需完整的TOP1000代币数据，请运行:');
    logInfo('  node scripts/init-top1000-tokens.js');
  }
}

// 错误处理
process.on('unhandledRejection', (error) => {
  logError(`未处理的错误: ${error.message}`);
  process.exit(1);
});

process.on('SIGINT', () => {
  log('\n\n👋 用户中断，退出设置...', 'yellow');
  process.exit(0);
});

// 如果直接运行此脚本
if (require.main === module) {
  setupDevelopmentEnvironment().catch((error) => {
    logError(`设置失败: ${error.message}`);
    process.exit(1);
  });
}

module.exports = { setupDevelopmentEnvironment }; 